package com.jorado.metrics.jvm;

import com.jorado.metrics.util.LabelHelp;
import com.jorado.metrics.util.VersionHelp;
import io.prometheus.client.Collector;
import io.prometheus.client.CounterMetricFamily;
import io.prometheus.client.GaugeMetricFamily;

import java.lang.management.ClassLoadingMXBean;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Exports metrics about JVM classloading.
 * <p>
 * Example usage:
 * <pre>
 * {@code
 *   new ClassLoadingExports().register();
 * }
 * </pre>
 * Example metrics being exported:
 * <pre>
 *   jvm_classes_loaded{} 1000
 *   jvm_classes_loaded_total{} 2000
 *   jvm_classes_unloaded_total{} 500
 * </pre>
 */
public class ClassLoadingExports extends Collector {
    private final ClassLoadingMXBean clBean;

    public ClassLoadingExports() {
        this(ManagementFactory.getClassLoadingMXBean());
    }

    public ClassLoadingExports(ClassLoadingMXBean clBean) {
        this.clBean = clBean;
    }

    void addClassLoadingMetrics(List<MetricFamilySamples> sampleFamilies) {
        GaugeMetricFamily loadedClassCount = new GaugeMetricFamily(
                "jvm_classes_loaded",
                "The number of classes that are currently loaded in the JVM." + VersionHelp.Ver,
                Arrays.asList(LabelHelp.addLabels()));
        sampleFamilies.add(loadedClassCount);
        CounterMetricFamily totalLoadedClassCount = new CounterMetricFamily(
                "jvm_classes_loaded_total",
                "The total number of classes that have been loaded since the JVM has started execution." + VersionHelp.Ver,
                Arrays.asList(LabelHelp.addLabels()));
        sampleFamilies.add(totalLoadedClassCount);
        CounterMetricFamily unloadedClassCount = new CounterMetricFamily(
                "jvm_classes_unloaded_total",
                "The total number of classes that have been unloaded since the JVM has started execution." + VersionHelp.Ver,
                Arrays.asList(LabelHelp.addLabels()));
        sampleFamilies.add(unloadedClassCount);
        loadedClassCount.addMetric(Arrays.asList(LabelHelp.addValues()), clBean.getLoadedClassCount());
        totalLoadedClassCount.addMetric(Arrays.asList(LabelHelp.addValues()), clBean.getTotalLoadedClassCount());
        unloadedClassCount.addMetric(Arrays.asList(LabelHelp.addValues()), clBean.getUnloadedClassCount());


    }


    public List<MetricFamilySamples> collect() {
        List<MetricFamilySamples> mfs = new ArrayList<MetricFamilySamples>();
        addClassLoadingMetrics(mfs);
        return mfs;
    }
}
